University of Washington
7/15/2019
Image courtesy of Jean Bilheux from the neutron imaging GitHub repository.
In [1]:
# Make sure needed packages are installed and up-to-date
import sys
!conda install --yes --prefix {sys.prefix} numpy scipy matplotlib scikit-learn Ipython ipywidgets h5py
!{sys.executable} -m pip install -U --no-deps pycroscopy # this will automatically install pyUSID as well
In [2]:
# Ensure python 3 compatibility
from __future__ import division, print_function, absolute_import
# Import necessary libraries:
# General utilities:
import os
import shutil
# Computation:
import numpy as np
import h5py
# Visualization:
# import ipympl
import matplotlib.pyplot as plt
import matplotlib.widgets as mpw
from IPython.display import display, clear_output, HTML
import ipywidgets as widgets
import pyUSID as usid
# Finally, pycroscopy itself
sys.path.append('..')
import pycroscopy as px
# Make Notebook take up most of page width
display(HTML(data="""
<style>
div#notebook-container { width: 90%; }
div#menubar-container { width: 65%; }
div#maintoolbar-container { width: 99%; }
</style>
"""))
In [3]:
# set up notebook to show plots within the notebook
%matplotlib notebook
In [4]:
max_mem = 1024*8 # Maximum memory to use, in Mbs. Default = 1024
max_cores = None # Number of logical cores to use in fitting. None uses all but 2 available cores.
Converting the raw data into a pycroscopy compatible hierarchical data format (HDF or .h5) file gives you access to the fast fitting algorithms and powerful analysis functions within pycroscopy
You can select desired file type by choosing the second option in the pull down menu on the bottom right of the file window
In [5]:
input_file_path = usid.io_utils.file_dialog(caption='Select translated .h5 file or raw experiment data',
file_filter='Parameters for raw BE data (*.txt *.mat *xls *.xlsx);; \
Translated file (*.h5)')
(data_dir, filename) = os.path.split(input_file_path)
if input_file_path.endswith('.h5'):
# No translation here
h5_path = input_file_path
force = True # Set this to true to force patching of the datafile.
tl = px.io.translators.LabViewH5Patcher()
tl.translate(h5_path, force_patch=force)
else:
# Set the data to be translated
data_path = input_file_path
(junk, base_name) = os.path.split(data_dir)
# # Check if the data is in the new or old format. Initialize the correct translator for the format.
# if base_name == 'newdataformat':
# (junk, base_name) = os.path.split(junk)
# translator = px.io.translators.BEPSndfTranslator(max_mem_mb=max_mem)
# else:
# translator = px.io.translators.BEodfTranslator(max_mem_mb=max_mem)
# if base_name.endswith('_d'):
# base_name = base_name[:-2]
# Translate the data
h5_path = translator.translate(data_path, show_plots=True, save_plots=False)
h5_file = h5py.File(h5_path, 'r+')
print('Working on:\n' + h5_path)
h5_main = usid.hdf_utils.find_dataset(h5_file, 'Raw_Data')[0]
The file contents are stored in a tree structure, just like files on a conventional computer. The data is stored as a 2D matrix (position, spectroscopic value) regardless of the dimensionality of the data. Thus, the positions will be arranged as row0-col0, row0-col1.... row0-colN, row1-col0.... and the data for each position is stored as it was chronologically collected
The main dataset is always accompanied by four ancillary datasets that explain the position and spectroscopic value of any given element in the dataset.
In [6]:
print('Datasets and datagroups within the file:\n------------------------------------')
usid.hdf_utils.print_tree(h5_file)
print('\nThe main dataset:\n------------------------------------')
print(h5_main)
print('\nThe ancillary datasets:\n------------------------------------')
print(h5_main.h5_pos_inds)
print(h5_main.h5_pos_vals)
print(h5_main.h5_spec_inds)
print(h5_main.h5_spec_vals)
print('\nMetadata or attributes in a datagroup\n------------------------------------')
for key, val in usid.hdf_utils.get_attributes(h5_main.parent.parent).items():
print('{} : {}'.format(key, val))
In [7]:
h5_pos_inds = h5_main.h5_pos_inds
pos_dims = h5_main.pos_dim_sizes
pos_labels = h5_main.pos_dim_labels
print(pos_labels, pos_dims)
parm_dict = h5_main.parent.parent.attrs
is_ckpfm = h5_file.attrs['data_type'] == 'cKPFMData'
if is_ckpfm:
num_write_steps = parm_dict['VS_num_DC_write_steps']
num_read_steps = parm_dict['VS_num_read_steps']
num_fields = 2
In [8]:
sho_fit_points = 5 # The number of data points at each step to use when fitting
sho_override = False # Force recompute if True
h5_main_SHO_fitter = px.analysis.BESHOfitter(h5_main, parallel=True, verbose=True)
h5_main_SHO_guess = h5_main_SHO_fitter.do_guess(strategy='complex_gaussian', options={'num_points':sho_fit_points},
processors=max_cores, max_mem=max_mem, override=sho_override)
h5_main_SHO_fit = h5_main_SHO_fitter.do_fit(processors=max_cores, max_mem=max_mem, override=sho_override)
In [9]:
starts_with = 'write'
#experimentally obtained tip sensitivity
tip_sens = 83.53 * 1e3 #pm/V
#phase offset to get raw phase centered at 0. can obtain by plotting:
# plt.hist(np.concatenate(h5_main_SHO_fit['Phase [rad]'].reshape(-1,1)), bins=1000);
phase = 3.0
#fit method, can be 'Exponential' 'Double_Exp' or 'Logistic'
fit_method = 'Double_Exp'
In [10]:
decayfit = px.analysis.BERelaxFit(h5_main_SHO_fit, sens=tip_sens, phase_off=phase, starts_with=starts_with, fit_method=fit_method)
#start and end positions should be 0, and spatial dimension of h5_main; currently is user specified because it has yet to be integrated to the BERelaxFit process class.
decayfit._start_pos = 0
decayfit._end_pos = h5_main.shape[0]
decayfit._cores = 1
#decayfit.compute()
In [11]:
h5_main_fit = h5_file['Measurement_000/Channel_000/Raw_Data-SHO_Fit_001/Fit-Double_Exp_000/Double_Exp_Fit']
#make widget sliders for x-, and y-axes, voltage, and time
slide_x = widgets.IntSlider(min=0, max=h5_main_SHO_fit.pos_dim_sizes[0] - 1, description='Col')
slide_y = widgets.IntSlider(min=0, max=h5_main_SHO_fit.pos_dim_sizes[1] - 1, description='Row')
slide_v = widgets.IntSlider(min=0, max=decayfit.no_rs_spectra-1, step=1, description='App. Voltage',
continuous_update=False, value = 0)
slide_t = widgets.IntSlider(min=0, max=decayfit.no_time_steps - 1, description='Time Slice',
continuous_update=False)
#make plotting interactive with widgets
widgets.interact(px.viz.be_viz_utils.viz_berelaxfit, berelaxfit = widgets.fixed(h5_main_fit), t_time=slide_t, x_col=slide_x, h_row=slide_y,
bias_ind=slide_v, sensitivity=widgets.fixed(tip_sens), phase_offset=widgets.fixed(phase), fit_method=widgets.fixed(fit_method), starts_with = widgets.fixed(starts_with));
In [ ]: